package hqb.dev.webdeploy.api;

import cn.hutool.core.util.StrUtil;
import hqb.dev.webdeploy.flow.FlowStep;
import hqb.dev.webdeploy.logic.UpdateFlow;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.input.ReversedLinesFileReader;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Comparator;
import java.util.List;

/**
 * @author HQB--2024-04-22
 **/
@RestController
@RequestMapping("deploy")
@Slf4j
public class DeployController {

    private static final File unzipDir = new File("/updatetmp").getAbsoluteFile();
    private static Thread deployThread;

    @RequestMapping("/start")
    public String deploy(@RequestBody DeployPrm prm) {
        if (deployThread != null && deployThread.isAlive()) {
            return "部署任务正在执行...";
        }
        log.info("流程开始.");
        deployThread = new Thread(() -> {
            try {
                startDeploy(prm);
                log.info("流程结束.");
            } catch (Exception e) {
                log.info("部署异常.", e);
            }
        });
        deployThread.start();
        return "Deploying...";
    }

    private void startDeploy(DeployPrm prm) {
        UpdateFlow updateFlow = new UpdateFlow(prm, unzipDir);
        if (!updateFlow.isState()) return;
        List<FlowStep> steps = updateFlow.getSteps();
        for (FlowStep step : steps) {
            log.info("执行步骤: " + step.getName());
            step.execute();
        }
        log.info("所有步骤执行完成.");
    }


    @RequestMapping("/logs")
    public DeployLogVo logs(@RequestBody DeployLogPrm prm) throws Exception {
        String dir = "./logs/deploy";
        DeployLogVo res = new DeployLogVo();
        readFiles(dir, res);
        readLogs(prm, dir, res);
        return res;
    }

    private void readFiles(String dir, DeployLogVo res) {
        File dirFile = new File(dir);
        if (dirFile.exists()) {
            File[] files = dirFile.listFiles();
            if (files != null) {
                for (File f : files) {
                    String name = f.getName();
                    if (f.isFile() && name.contains(".run.")) {
                        res.getFiles().add(name);
                    }
                }
            }
        }
    }

    private void readLogs(DeployLogPrm prm, String dir, DeployLogVo res) throws IOException {
        String fname = prm.getFname();
        if (StrUtil.isEmpty(fname)) {
            List<String> files = res.getFiles();
            if (files.isEmpty()) return;
            fname = files.stream()
                    .map(split -> split.split("\\."))
                    .max(Comparator.comparingInt(arr -> Integer.parseInt(arr[2])))
                    .map(arr -> String.join(".", arr))
                    .get();
        }
        File file = new File(dir, fname);
        if (file.exists()) {
            Integer count = prm.getLine();
            if (count == null) {
                count = 100;
            }
            res.getLogs().addAll(ReversedLinesFileReader.builder()
                    .setFile(file)
                    .setBufferSize(4096)
                    .setCharset(StandardCharsets.UTF_8)
                    .get()
                    .readLines(count)
                    .reversed());
        }
    }
}
